package com.yubest;

import java.util.ArrayList;
import java.util.List;

/**
 * 给你一个 m 行 n 列的矩阵 matrix ，请按照 顺时针螺旋顺序 ，返回矩阵中的所有元素。
 *
 *
 *
 * 示例 1：[图片] img/0054_1.jpg
 *
 *
 * 输入：matrix = [[1,2,3],[4,5,6],[7,8,9]]
 * 输出：[1,2,3,6,9,8,7,4,5]
 * 示例 2：[图片] img/0054_2.jpg
 *
 *
 * 输入：matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
 * 输出：[1,2,3,4,8,12,11,10,9,5,6,7]
 *
 *
 * 提示：
 *
 * m == matrix.length
 * n == matrix[i].length
 * 1 <= m, n <= 10
 * -100 <= matrix[i][j] <= 100
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/spiral-matrix
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 * @Author hweiyu
 * @Description
 * @Date 2021/11/26 9:23
 */
public class P0054 {
}

class Solution54 {

    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> result = new ArrayList<>();
        //行长度
        int m = matrix.length;
        //列长度
        int n = matrix[0].length;
        //方向
        Direct direct = Direct.RIGHT;
        //行坐标
        int row = 0;
        //列坐标
        int col = 0;
        //用于标记matrix[row][col]是否已经被遍历过，随意设置一个操作范围的数即可
        final int FLAG = 101;
        for (;;) {
            result.add(matrix[row][col]);
            //将当前数标记为已遍历状态
            matrix[row][col] = FLAG;
            if (direct == Direct.UP) {
                if (row - 1 < 0 || FLAG == matrix[row - 1][col]) {
                    if (col + 1 >= n || FLAG == matrix[row][col + 1]) {
                        break;
                    }
                    direct = direct.next();
                    col++;
                } else {
                    row--;
                }
            } else if (direct == Direct.DOWN) {
                if (row + 1 >= m || FLAG == matrix[row + 1][col]) {
                    if (col - 1 < 0 || FLAG == matrix[row][col - 1]) {
                        break;
                    }
                    direct = direct.next();
                    col--;
                } else {
                    row++;
                }
            } else if (direct == Direct.LEFT) {
                if (col - 1 < 0 || FLAG == matrix[row][col - 1]) {
                    if (row - 1 < 0 || FLAG == matrix[row - 1][col]) {
                        break;
                    }
                    direct = direct.next();
                    row--;
                } else {
                    col--;
                }
            } else if (direct == Direct.RIGHT) {
                if (col + 1 >= n || FLAG == matrix[row][col + 1]) {
                    if (row + 1 >= m || FLAG == matrix[row + 1][col]) {
                        break;
                    }
                    direct = direct.next();
                    row++;
                } else {
                    col++;
                }
            }
        }
        return result;
    }
}

enum Direct {

    /**
     * 方向，上下左右
     */
    UP, DOWN, LEFT, RIGHT;

    /**
     * 下一个方向
     * @return
     */
    public Direct next() {
        if (this == Direct.UP) {
            return Direct.RIGHT;
        } else if (this == Direct.DOWN) {
            return Direct.LEFT;
        } else if (this == Direct.LEFT) {
            return Direct.UP;
        } else if (this == Direct.RIGHT) {
            return Direct.DOWN;
        }
        return null;
    }
}
